package com.xiaolin.oa.handler;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xiaolin.oa.annotations.NotControllerResponseAdvice;
import com.xiaolin.oa.enums.StatusCode;
import com.xiaolin.oa.utils.OptResult;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * @author xiaolin
 * @Description 统一封装响应结果
 * @email xiaolin@gmail.com
 * @date 2022/8/5 22:48
 */
@RestControllerAdvice(basePackages = {"com.xiaolin.oa.controller"})
public class ControllerResponseAdvice implements ResponseBodyAdvice<Object> {
    /**
     * 过滤掉不封装的类型
     *
     * @param returnType
     * @param converterType
     * @return
     */
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 类型是 HandleResult 或方法上有 NotControllerResponseAdvice 注解则不封装结果集
        return !(returnType.getParameterType().isAssignableFrom(OptResult.class)
                || returnType.hasMethodAnnotation(NotControllerResponseAdvice.class));
    }

    /**
     * 封装结果集
     *
     * @param body
     * @param returnType
     * @param selectedContentType
     * @param selectedConverterType
     * @param request
     * @param response
     * @return
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        // String类型不能直接包装，因为字符串无法直接封装成json
        if (returnType.getGenericParameterType().equals(String.class)) {
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                // 将数据包装在 Result 里后转换为 json串进行返回
                return objectMapper.writeValueAsString(OptResult.ok(body));
            } catch (JsonProcessingException e) {
                return OptResult.fail(StatusCode.SYS_ERR, e.getMessage());
            }
        }
        if (returnType.getGenericParameterType().equals(Boolean.class) || returnType.getGenericParameterType().equals(boolean.class)) {
            // 如果是布尔值，则 true 返回 ok，false 返回 fail
            return OptResult.optFlag((Boolean) body);
        }
        // 其他数据则进行封装
        return OptResult.ok(body);
    }
}
